import re

# Funcion para crear un objeto de tipo TimeCode a partir de un string ("08:37:45:17" o "08:37:45;17") y de un entero con el Frame Rate

def timeCodeFromString(timeCode, frameRate):
    if re.search(";", timeCode):
	if (frameRate != 29.97):
	    raise Exception, "Invalid FrameRate"
	    return None
    try:
	tc = TimeCode()
	tc.setFrameRate(frameRate)
	tc.setTimeCode(timeCode)
	return tc
    except:
	return None


# Funcion para crear un objeto de tipo TimeCode a partir de un entero con la cantidad de frames y un entero con el Frame Rate

def timeCodeFromFrames(frames, frameRate):
    try:
	tc = TimeCode()
	tc.setFrameRate(frameRate)
	tc.setFrames(frames)
	return tc
    except:
	return None


# Clase TimeCode

class TimeCode(object):
    
    def __init__(self):
	self.__frames = 0		#Frames desde cero del objeto TC
	self.__string = "00:00:00:00"	#TC en formato string
	self.__frameRate = 30		#frameRate asociado al TC
	self.__miliSeconds = 0		#milisegundos desde cero
	
    def __add__(self, other):
	if self.__frameRate == other.getFrameRate():
	    frames = self.__frames + other.getFrames()
	    ret = TimeCode()
	    ret.setFrameRate(self.__frameRate)
	    ret.setFrames(frames)
	    return ret
	else:
	    print "FrameRate does not match"
	    return None

    def __sub__(self, other):
	if self.__frameRate == other.getFrameRate():
	    frames = self.__frames - other.getFrames()
	    ret = TimeCode()
	    ret.setFrameRate(self.__frameRate)
	    ret.setFrames(frames)
	    return ret
	else:
	    print "FrameRate does not match"
	    return None
	
    def __eq__(self, other):
	if self.__frameRate == other.getFrameRate():
	    if self.__frames == other.getFrames():
		return True
	else:
	    print "FrameRate does not match"
	return False

    def __ne__(self, other):
	if self.__frameRate != other.getFrameRate():
	    if self.__frames != other.getFrames():
		return True
	else:
	    print "FrameRate does not match"
	return False

    def __ne__(self, other):
	if self.__frameRate == other.getFrameRate():
	    if self.__frames != other.getFrames():
		return True
	else:
	    print "FrameRate does not match"
	return False

    def __lt__(self, other):
	if self.__frameRate == other.getFrameRate():
	    if self.__frames < other.getFrames():
		return True
	else:
	    print "FrameRate does not match"
	return False

    def __le__(self, other):
	if self.__frameRate == other.getFrameRate():
	    if self.__frames <= other.getFrames():
		return True
	else:
	    print "FrameRate does not match"
	return False

    def __ge__(self, other):
	if self.__frameRate == other.getFrameRate():
	    if self.__frames >= other.getFrames():
		return True
	else:
	    print "FrameRate does not match"
	return False

    def __gt__(self, other):
	if self.__frameRate == other.getFrameRate():
	    if self.__frames > other.getFrames():
		return True
	else:
	    print "FrameRate does not match"
	return False


    def __tcToArray(self):
	tcArray = self.__string.split(":")
	return tcArray
	
	

    def __validateFrameRate(self, frameRate):
	if frameRate == 29.97 or frameRate == 30 or frameRate == 25 or frameRate == 23.976 or frameRate == 24:
	    return True
	else:
	    return False


    def __framesToTc(self):
	if self.__frameRate ==  29.97:
	    hh, ff = divmod(self.__frames, 107892)
	    mm = int((self.__frames + (2 * int(ff / 1800)) - (2 * (int(ff / 18000))) - (107892 * hh)) / 1800)
	    ss = int((self.__frames - (1798 * mm) - (2 * int(mm / 10)) - (107892 * hh)) / 30)
	    ff = int(self.__frames - (30 * ss) - (1798 * mm) - (2 * int(mm / 10)) - (107892 * hh))
	
	elif self.__frameRate == 23.976:
	    pass
	
	elif self.__frameRate == 30 or self.__frameRate == 25 or self.__frameRate == 24:
	    ss, ff = divmod( int(self.__frames), int(self.__frameRate) )
	    mm, ss = divmod( ss, 60 )
	    hh, mm = divmod( mm, 60 )
	
	else:
	    return -1
	
	if ff < 10:
	    ff = "0" + str(ff)
	if ss < 10:
	    ss = "0" + str(ss)
	if mm < 10:
	    mm = "0" + str(mm)
	if hh < 10:
	    hh = "0" + str(hh)
	timeCode = str(hh) + ":" + str(mm) + ":" + str(ss) + ":" + str(ff)
	return timeCode


    def __getFramesFromZero(self):
	tcArray = self.__tcToArray()
	if self.__frameRate == 29.97:
	    totalMinutes = 60 * int(tcArray[0]) + int(tcArray[1])
	    totalFrames  = 108000 * int(tcArray[0]) + 1800 * int(tcArray[1]) + 30 * int(tcArray[2]) + int(tcArray[3]) - 2 * (totalMinutes - int(totalMinutes / 10))
	
	elif self.__frameRate == 23.976:
	    pass
	    
	elif self.__frameRate == 30 or self.__frameRate == 25 or self.__frameRate == 24:
	    totalSeconds = (int(tcArray[0]) * 3600) + (int(tcArray[1]) * 60) + int(tcArray[2])
	    totalFrames = (totalSeconds * self.__frameRate) + int(tcArray[3])
	
	else:
	    return -1
	
	return totalFrames


    def setTimeCode(self, tc):
	if re.search(";", tc):
	    self.__frameRate = 29.97
	    tc = re.sub(";", ":", tc)

	tcRet = re.match("([0-9][0-9]):([0-5][0-9]):([0-5][0-9]):([0-2][0-9])", tc)
	
	if tcRet:
	    if self.__frameRate == 29.97:
		if int(tcRet.group(4)) < 30:
		    #chequeos para NDF: cada un minuto saltea dropea dos frames
		    pass
		else:
		    print "TC invalido"
		    return False
	    elif self.__frameRate == 23.976:
		if int(tcRet.group(4)) < 24:
		    #chequeos para 23.976: ???
		    pass
		else:
		    print "TC invalido"
		    return False
	    elif self.__frameRate == 30 or self.__frameRate == 25 or self.__frameRate == 24:
		if int(tcRet.group(4)) >= self.__frameRate:
		    print "TC invalido"
		    return False
	    else:
		print "Frame Rate no soportado"
		return False
	else:
	    print "TC invalido"
	    return False
	self.__string = tc
	self.__frames = self.__getFramesFromZero()
	return True



    def setFrameRate(self, frameRate):
	if self.__validateFrameRate(frameRate):
	    self.__frameRate = frameRate
	    self.__string = self.__framesToTc()
	    return True
	else:
	    return False

    def setFrames(self, frames):
	if frames >= 0:
	    self.__frames = frames
	    self.__string = self.__framesToTc()
	    return True
	else:
	    return False

    def getTimeCode(self):
	return self.__string

    def getFrameRate(self):
	return self.__frameRate

    def getFrames(self):
	return self.__frames

    def getMiliSeconds(self):
	return self.__miliSeconds

